#ifndef __STEP_MOTOR_DRIVER_H__
#define __STEP_MOTOR_DRIVER_H__

#include <vector>

enum StepMotorMotionMode {
    STEP_MOTOR_NORMAL_PULSE_MODE,
    STEP_MOTOR_NORMAL_INFINITY_MODE,
    STEP_MOTOR_HIRES_PULSE_MODE,
    STEP_MOTOR_HIRES_INFINITY_MODE
};

enum StepMotorMotionState {
    STEP_MOTOR_STOPPED,
    STEP_MOTOR_RUNNING
};

enum StepMotorLimitState {
    STEP_MOTOR_UNLIMITED,
    STEP_MOTOR_LIMITED
};

enum StepMotorFlagState {
    STEP_MOTOR_YET,
    STEP_MOTOR_DONE
};

enum StepMotorSpeedTrend {
    STEP_MOTOR_SLOW_DOWN,
    STEP_MOTOR_SPEED_UP
};

struct StepMotorMotionInfo {
    bool motion_state;
    int motion_pulse;
};

struct StepMotorLimitInfo {
    bool limit_state;
    bool direction;
};

struct StepMotorResetInfo {
    bool  reset_flag;               // 复位标志位
	int  reset_dir;				    // 复位方向
    int  reset_distance;      
};

struct StepMotorAbsolutePositionInfo {
    bool  read_flag;                // 可读标志位
	int  absolute_position;         // 绝对位置   
};

struct StepMotorRelativePositionInfo {
    bool  read_flag;                // 可读标志位
	int  relative_position;         // 相对位置
};

class StepMotorDriver;

class StepMotorReceiveData {
public:
    void parseUartReceiveData(char* buf, int len);
    void attach(StepMotorDriver* driver) { driver_group_.push_back(driver); }

private:
    std::vector<StepMotorDriver*> driver_group_;
};

class StepMotorDriver {
public:
    StepMotorDriver(int motor_id) : motor_id_(motor_id) { processRecvData().attach(this); }     // 每次构造都将自己加入观察者
 
    static int initMotor();

    int getMotorId() const { return motor_id_; }
    void updateMotionState(bool motion_state) { motion_info_.motion_state = motion_state; }
    void updateMotionPulse(int motion_pulse) { motion_info_.motion_pulse = motion_pulse; }
    void updateLimitInfo(const StepMotorLimitInfo& limit_info) { limit_info_ = limit_info; }
    void updateResetInfo(const StepMotorResetInfo& reset_info) { reset_info_ = reset_info; }
    void updateAbsolutePosition(const StepMotorAbsolutePositionInfo& absolute_position_info) { absolute_position_info_ = absolute_position_info; }
    void updateRelativePosition(const StepMotorRelativePositionInfo& relative_position_info) { relative_position_info_ = relative_position_info; }

    int run(int mode, int mStep, int direction, int frequency, int pulse, int accelStep);
    int stop(int stopMode, int keepTorque, int decelStep);
    int checkMotionState();
    int setDirection(int direction);
    int setMStep(int mStep);
    int setFrequency(int trend, int frequency, int accelStep);
    int reset(int direction);
    int readAbsolutePosition(int mStep);
    int readRelativePosition();
    int disableLimit(int limitSwitchX);
    
    bool getMotionState();
    int getMotionPulse();
    bool getLimitState();
    bool getLimitState(int direciton);
    int getRelativePosition();
    int getAbsolutePosition();
    int getResetState();

private:
    static void uartRecvThread();
    static StepMotorReceiveData& processRecvData() { static StepMotorReceiveData recv_data; return recv_data; }

private:
    static int fd_;
    const int motor_id_;
    StepMotorMotionInfo motion_info_ = {STEP_MOTOR_STOPPED, -1};
    StepMotorLimitInfo limit_info_ = {STEP_MOTOR_UNLIMITED, 0};
    StepMotorResetInfo reset_info_ = {STEP_MOTOR_YET, 0, 0};
    StepMotorAbsolutePositionInfo absolute_position_info_ = {STEP_MOTOR_YET, 0};
    StepMotorRelativePositionInfo relative_position_info_ = {STEP_MOTOR_YET, 0};
};



#endif